package com.yanqu.road.server.manager.activity.fivehero;

import com.google.protobuf.AbstractMessage;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.camp.CampUnion;
import com.yanqu.road.entity.activity.fivehero.FiveHeroConfig;
import com.yanqu.road.entity.activity.fivehero.config.FiveHeroBookConfig;
import com.yanqu.road.entity.activity.fivehero.config.FiveHeroTitleConfig;
import com.yanqu.road.entity.activity.fivehero.cross.*;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eMessageType;
import com.yanqu.road.entity.enums.eSceneType;
import com.yanqu.road.entity.log.cross.fivehero.LogFiveHeroBook;
import com.yanqu.road.entity.log.cross.fivehero.LogFiveHeroPatronsUpdate;
import com.yanqu.road.entity.log.cross.fivehero.LogFiveHeroUnion;
import com.yanqu.road.entity.log.cross.fivehero.LogFiveHeroUserHp;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.scene.ScenePlayerInfo;
import com.yanqu.road.entity.scene.UserScene;
import com.yanqu.road.logic.bussiness.activity.FiveHeroBusiness;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.FiveHeroProto;
import com.yanqu.road.pb.commonactivity.CommonActivityProto;
import com.yanqu.road.pb.cross.activity.CrossActivityProto;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityChatMgr;
import com.yanqu.road.server.manager.activity.camp.CampApi;
import com.yanqu.road.server.manager.activity.camp.eCampActivityType;
import com.yanqu.road.server.manager.activity.fivehero.logic.CrossFiveHeroChatLogic;
import com.yanqu.road.server.manager.config.GoodsMgr;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.scene.CrossSceneMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.*;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.stream.Collectors;

public class CrossFiveHeroActivity implements CampApi {

    private Logger logger = LogManager.getLogger(CrossFiveHeroActivity.class.getName());

    private RandomHelper randomHelper = new RandomHelper();

    //重启就去找商会跨服更新下全部的
    private boolean updateAllUnion = false;

    private int groupId;

    private FiveHeroConfig config;


    // 聊天
    private CrossFiveHeroChatLogic chatLogic;

    /**
     * 大锁
     */
    protected final Object lock = new Object();

    private CrossFiveHeroData crossFiveHeroData;

    private Map<String, CrossFiveHeroUnion> unionMap = new ConcurrentHashMap<>();

    private Map<Long, CrossFiveHeroUserData> userDataMap = new ConcurrentHashMap<>();

    //比賽 現在只有一场，都是1，为以后的癫疯做准备
    private Map<Integer, CrossFiveHeroMatch> matchMap = new ConcurrentHashMap<>();

    private List<CrossFiveHeroUserData> needInsertUserDataList = new ArrayList<>();
    private List<CrossFiveHeroUserData> needUpdateUserDataList = new ArrayList<>();

    private List<CrossFiveHeroPatrons> needInsertPatronsDataList = new ArrayList<>();
    private List<CrossFiveHeroPatrons> needUpdatePatronsDataList = new ArrayList<>();

    private List<CrossFiveHeroBookData> needInsertBookDataList = new ArrayList<>();
    private List<CrossFiveHeroBookData> needUpdateBooksDataList = new ArrayList<>();

    public CrossFiveHeroActivity(ActivityInfo tmpActivityInfo,FiveHeroConfig tempConfig,int inGroupId) {
        logger.warn("五熊启动");
        groupId = inGroupId;
        config = tempConfig;

        chatLogic = new CrossFiveHeroChatLogic(getActivityInfo(),config.getChatNum());

        crossFiveHeroData = FiveHeroBusiness.getCrossFiveHeroData(tmpActivityInfo.getActivityId(),groupId);
        if(crossFiveHeroData == null){
            crossFiveHeroData = new CrossFiveHeroData();
            crossFiveHeroData.setGroupId(groupId);
            crossFiveHeroData.setActivityId(tmpActivityInfo.getActivityId());
            crossFiveHeroData.setLockUnion(false);
            crossFiveHeroData.setInsertOption();
        }else{
            crossFiveHeroData.setBookMap(FiveHeroBusiness.getCrossBookDataMap(tmpActivityInfo.getActivityId(),groupId));
            //有个字段没入库，读出来要重新设置一下可以不可以领取书的奖励
            Map<Integer, FiveHeroBookConfig> bookConfigMap = config.getBookConfigMap();
            Map<String, Map<Integer, CrossFiveHeroBookData>> unionBookMap = crossFiveHeroData.getBookMap();
            for(Map<Integer, CrossFiveHeroBookData> bookMap : unionBookMap.values()){
                for(CrossFiveHeroBookData bookData : bookMap.values()){
                    if(bookData.getNo() <= bookConfigMap.size()){
                        bookData.setCanGetReward(true);
                    }
                }
            }
        }



        userDataMap = FiveHeroBusiness.getCrossUserDataMap(tmpActivityInfo.getActivityId(),groupId);
        Map<Long, Map<Integer,CrossFiveHeroPatrons>> patronsMap = FiveHeroBusiness.getCrossPatronsDataMap(tmpActivityInfo.getActivityId(),groupId);
        setUserPatrons(patronsMap);

        unionMap = FiveHeroBusiness.getCrossFiveHeroUnionData(tmpActivityInfo.getActivityId(),groupId);

        Map<Integer,CrossFiveHeroMatchData> matchDbMap = FiveHeroBusiness.getCrossFiveHeroMatchData(tmpActivityInfo.getActivityId(),groupId);
        Map<Integer, CrossFiveHeroCity> cityMap = FiveHeroBusiness.getCrossCityDataMap(tmpActivityInfo.getActivityId(),groupId);
        Map<Long,List<CrossFiveHeroUserReport>> userReportMap = FiveHeroBusiness.getCrossUserReportDataMap(tmpActivityInfo.getActivityId(),config.getCityReportNum(),groupId);
        int luoyangCityId = config.getLuoYangId();
        List<CrossFiveHeroCityReport> cityReportMap = FiveHeroBusiness.getCrossCityReportDataMap(tmpActivityInfo.getActivityId(),config.getCityReportNum(),groupId,luoyangCityId);
        List<CrossFiveHeroCityReport> cityReportLuoYangMap = FiveHeroBusiness.getCrossCityLuoYangReportDataMap(tmpActivityInfo.getActivityId(),config.getCityReportNum(),groupId,luoyangCityId);
        for(CrossFiveHeroMatchData matchData : matchDbMap.values()){
            matchData.setCityMap(cityMap);
            CrossFiveHeroMatch match = new CrossFiveHeroMatch(config,matchData);
            match.addUnionData(unionMap);
            match.addUserData(userDataMap);
            match.addUserReportData(userReportMap);
            match.addCityReportData(cityReportMap);
            match.addCityReportLuoYangData(cityReportLuoYangMap);
            match.initFromDbData();
            match.putFiveHeroActivity(this);
            matchMap.put(match.getCrossFiveHeroMatchData().getMatchId(),match);
        }
    }

    //给玩家分配他的门客
    private void setUserPatrons(Map<Long, Map<Integer,CrossFiveHeroPatrons>> patronsMap){
        for(CrossFiveHeroUserData userData : userDataMap.values()){
            if(patronsMap.containsKey(userData.getUserId())){
                userData.setPatronsMap(patronsMap.get(userData.getUserId()));
            }
        }
    }

    public void addNeedInsertUserData(CrossFiveHeroUserData userData){
        synchronized (needInsertUserDataList){
            if(!needInsertUserDataList.contains(userData)){
                needInsertUserDataList.add(userData);
            }
        }
    }

    public void addNeedUpdateUserData(CrossFiveHeroUserData userData){
        synchronized (needUpdateUserDataList){
            if(!needUpdateUserDataList.contains(userData)){
                needUpdateUserDataList.add(userData);
            }
        }
    }

    public void addNeedInsertPatronsData(CrossFiveHeroPatrons patrons){
        synchronized (needInsertPatronsDataList){
            if(!needInsertPatronsDataList.contains(patrons)){
                needInsertPatronsDataList.add(patrons);
            }
        }
    }

    public void addNeedUpdatePatronsData(CrossFiveHeroPatrons patrons){
        synchronized (needUpdatePatronsDataList){
            if(!needUpdatePatronsDataList.contains(patrons)){
                needUpdatePatronsDataList.add(patrons);
            }
        }
    }

    public void addNeedInsertBookData(CrossFiveHeroBookData data){
        synchronized (needInsertBookDataList){
            if(!needInsertBookDataList.contains(data)){
                needInsertBookDataList.add(data);
            }
        }
    }

    public void addNeedUpdateBookData(CrossFiveHeroBookData data){
        synchronized (needUpdateBooksDataList){
            if(!needUpdateBooksDataList.contains(data)){
                needUpdateBooksDataList.add(data);
            }
        }
    }

    public ActivityInfo getActivityInfo(){
        return config.getActivityInfo();
    }

    public void timerTask() {
        lockUnionSendTask();
        checkPatronsTask();
        makeMatchTask();
        for(CrossFiveHeroMatch match : matchMap.values()){
            match.timerTask();
        }
        checkCityLord();
    }


    //设置城主
    private void checkCityLord(){
        if(config.getOpenCityLord() == 0){
            return;
        }
        Map<Integer, Long> winnerMap = crossFiveHeroData.getWinnerMap();
        synchronized (winnerMap){
            winnerMap = crossFiveHeroData.getWinnerMap();
            long  nowTime = System.currentTimeMillis();
            ActivityInfo activityInfo = config.getActivityInfo();
            if(nowTime < activityInfo.getEndTime() * 1000 + DateHelper.MINUTE_MILLIONS * 5 || winnerMap.size() != 0){
//            if(winnerMap.size() != 0){
                return;
            }
            CrossFiveHeroMatch match = getMatch();
            if(match != null){
                LinkedList<CrossFiveHeroRank> rankList = match.getCampScoreRankList(true);
                int rankNum = 0;
                for(CrossFiveHeroRank rank : rankList){
                    rankNum++;
                    int campId = Integer.valueOf(rank.getId());
//                    long unionMasterId = match.getTopPopularityUnionMasterId(campId);
                    //第一个
                    if(rankNum == 1){
                        //优化了，第一名的总的职位，第二名对应阵营职位
                        long userId1 = match.getRankPopularity(campId,1);
                        long userId2 = match.getRankPopularity(campId,2);
                        winnerMap.put(0,userId1);
                        winnerMap.put(campId,userId2);
                    }else{
                        long userId1 = match.getRankPopularity(campId,1);
                        winnerMap.put(campId,userId1);
                    }
                }
                crossFiveHeroData.setWinnerMap(winnerMap);
                for(int campId : winnerMap.keySet()){
                    FiveHeroTitleConfig titleConfig = config.getTitleConfig(campId);
                    if(titleConfig != null){
                        FiveHeroProto.CrossFiveHeroWinnerAppointSyncMsg.Builder syncMsg = FiveHeroProto.CrossFiveHeroWinnerAppointSyncMsg.newBuilder();
                        syncMsg.setPosition(titleConfig.getId());
                        syncMsg.setSendReward(true);
                        long userId = winnerMap.get(campId);
                        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
                        if(userId != 0 && userBaseInfo != null){
                            MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, YanQuMessageUtils.buildMessage(GameProtocol.S_FIVEHERO_APPOINT_FROM_CROSS, syncMsg));
                        }
                    }
                }
            }
        }
    }

    //校验门客是不是都上传完了
    private void checkPatronsTask(){
        synchronized (lock){
            if(unionMap.size() == 0 || crossFiveHeroData.isLockPatrons()){
                return;
            }
            logger.info("活动{} 分组{} 五熊争霸校验门客上传是否完成", getActivityInfo().getActivityId(), groupId);
            Map<Long,List<Long>> serverUserIdMap = new ConcurrentHashMap<>();
            for(CrossFiveHeroUnion union : unionMap.values()){
                for(CrossFiveHeroUnionMember member : union.getMemberMap().values()){
                    CrossFiveHeroUserData userData = getUserData(member.getUserId());
                    if(userData.getPatronsMap().size() == 0){
                        if(!serverUserIdMap.containsKey(member.getServerId())){
                            serverUserIdMap.put(member.getServerId(),new ArrayList<>());
                        }
                        serverUserIdMap.get(member.getServerId()).add(userData.getUserId());
                        logger.info("活动{} 分组{} 玩家{}没有门客", getActivityInfo().getActivityId(), groupId, userData.getUserId());
                    }
                }
            }
            if(serverUserIdMap.size() > 0){
                for(long serverId : serverUserIdMap.keySet()){
                    FiveHeroProto.CrossFiveHeroUpdatePatronsReqMsg.Builder userMsg = FiveHeroProto.CrossFiveHeroUpdatePatronsReqMsg.newBuilder();
                    userMsg.setGroupId(groupId);
                    userMsg.setActivityId(getActivityInfo().getActivityId());
                    userMsg.addAllUserIdList(serverUserIdMap.get(serverId));
                    MessageHelper.sendPacket(serverId, 0,
                            YanQuMessageUtils.buildMessage(GameProtocol.S_FIVEHERO_CROSS_GET_PATRONS, userMsg));
                }
                logger.info("活动{} 分组{} 去游戏服拉取玩家门客", getActivityInfo().getActivityId(), groupId);
                return;
            }

            logger.info("活动{} 分组{} 五熊争霸校验门客上传完成", getActivityInfo().getActivityId(), groupId);
            crossFiveHeroData.setLockPatrons(true);
        }
    }

    private void makeMatchTask(){
        if (!crossFiveHeroData.isLockUnion() || !crossFiveHeroData.isLockPatrons()) {
            return;
        }
        //不是巅峰，只有一场
        if(matchMap.size() > 0){
            return;
        }
        CrossFiveHeroMatch match = new CrossFiveHeroMatch(config,groupId);
        match.addUnionData(unionMap);
        match.addUserData(userDataMap);
        match.initData();
        match.putFiveHeroActivity(this);
        matchMap.put(match.getCrossFiveHeroMatchData().getMatchId(),match);
        // 同步报名状态
        for (Long userId : userDataMap.keySet()) {
            syncUserDataMsg(userId);
        }
    }

    private void lockUnionSendTask(){
        if (crossFiveHeroData.isLockUnion()) {
            if(!updateAllUnion){
                // 没赚钱的拉一下
                List<String> unionIdList = new ArrayList<>();
                for (CrossFiveHeroUnion union : unionMap.values()) {
                    //去跨服拉一下职位，没职位我日
                    unionIdList.add(union.getUnionUid());
                }
                sendGetUnionMsg(unionIdList);
            }
            return;
        }
        long nowTime = System.currentTimeMillis();
        if (nowTime > config.getRegisterTimeList().get(1)) {
            List<Long> serverList = config.getActivityInfo().getServerIdList();
            int index = randomHelper.next(0,serverList.size());
            long serverId = serverList.get(index);
            MessageHelper.sendPacket(serverId, 0,
                    YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_UNION_MAX_ABILITY_RANK_LOCK,
                            CommonActivityProto.CommonActivityRankListReqMsg.newBuilder().setGroupId(groupId).setActivityId(config.getActivityInfo().getActivityId())));
        }
    }

    /**
     * 锁定商会
     */
    public void lockUnion(RankProto.CrossUnionRankListLockMsg lockMsg) {
        List<Long> syncList = new ArrayList<>();
        synchronized (lock) {
            if (crossFiveHeroData.isLockUnion()) {
                return;
            }
            if(System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000L){
                return;
            }
            List<RankProto.CrossUnionRankLockTemp> rankList = lockMsg.getRankList();

            // 遍历数据一个个处理
            int i = 0;//加入计数
            for (RankProto.CrossUnionRankLockTemp unionMsg : rankList) {
                if(i < config.getSignUpUnionCount()){
                    // 【商会处理】
                    CrossFiveHeroUnion union = unionMap.get(unionMsg.getRankTemp().getUnionUid());
                    if (union == null) {
                        union = new CrossFiveHeroUnion();
                        union.setActivityId(config.getActivityInfo().getActivityId());
                        union.setGroupId(groupId);
                        union.setUnionUid(unionMsg.getRankTemp().getUnionUid());
                        union.setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(unionMsg.getRankTemp().getUnionBaseData()));
                        union.setMemberMap(new ConcurrentHashMap<>());
                        //已经拉过来是多少就是多少了，不用再去本服更新来更新去了，这个已经是历史最高赚钱了
                        union.setTotalAbility(Long.valueOf(unionMsg.getRankTemp().getValue()));
                        union.setInsertOption();
                        unionMap.put(union.getUnionUid(), union);
                    }

                    // 【成员处理】
                    Map<Long, CrossFiveHeroUnionMember> memberMap = new ConcurrentHashMap<>();
                    for (RankProto.CrossUnionMemberTemp msg : unionMsg.getMemberList()) {
                        CrossFiveHeroUnionMember member = new CrossFiveHeroUnionMember(msg.getMemberId(), msg.getServerId());
//                        member.setPosition(msg.getPosition());
                        memberMap.put(member.getUserId(), member);
                        syncList.add(member.getUserId()); // 添加报名状态同步
                    }
                    union.setMemberMap(memberMap);
                }
                CrossFiveHeroUnion union = unionMap.get(unionMsg.getRankTemp().getUnionUid());
                if(union == null){
                    // 日志 没有入围的先寄一下
                    CrossAutoLogMgr.add(new LogFiveHeroUnion(
                            groupId,
                            config.getActivityInfo().getActivityId(),
                            unionMsg.getRankTemp().getUnionUid(),
                            0,
                            UnionBasePb.parseUnionBaseInfo(unionMsg.getRankTemp().getUnionBaseData()).getTotalEarnSpeed().toString(),
                            unionMsg.getRankTemp().getValue(),
                            0
                    ));
                }
                i++;
            }
            // 排序拿前几名
            List<CrossFiveHeroUnion> unionRankList = unionMap.values().stream()
                    .sorted(new Comparator<CrossFiveHeroUnion>() {
                        @Override
                        public int compare(CrossFiveHeroUnion o1, CrossFiveHeroUnion o2) {
                            // 922 3372 0368亿
                            return Long.compare(o2.getTotalAbility(), o1.getTotalAbility());
                        }
                    })
                    .limit(config.getSignUpUnionCount())
                    .collect(Collectors.toList());

            for (int j = 0; j < unionRankList.size(); j++) { // 总赚钱排名
                CrossFiveHeroUnion union = unionRankList.get(j);
                union.setRank(j + 1);
            }

            // 分阵营
            List<Integer> groupParams = config.getGroupParams(); // 6;20
            if (groupParams.isEmpty()) { // 如果未配置特殊分组范围，就走旧的分配阵营逻辑
                makeCamp(unionRankList);
            } else {
                List<Integer> secondMatchRanges = config.secondMatchRanges();
                if (secondMatchRanges.isEmpty()) {
                    logger.error("五雄争霸 activity {} union lock error. 商会分组范围参数没配置", config.getActivityInfo().getActivityId());
                    return;
                }
                makeCamp(unionRankList, secondMatchRanges);
            }

            for(CrossFiveHeroUnion union : unionRankList){
                CrossAutoLogMgr.add(new LogFiveHeroUnion(
                        groupId,
                        config.getActivityInfo().getActivityId(),
                        union.getUnionUid(),
                        union.getCampId(),
                        union.getUnionBaseInfo().getTotalEarnSpeed().toString(),
                        union.getCampId() == 0 ? "-1" : union.getTotalAbility() + "",
                        union.getCampId() != 0 ? 1 : 0
                ));
            }
            // 没赚钱的拉一下
            List<String> unionIdList = new ArrayList<>();
            for (CrossFiveHeroUnion union : unionRankList) {
                //去跨服拉一下职位，没职位我日
                unionIdList.add(union.getUnionUid());
            }
            sendGetUnionMsg(unionIdList);

            //补丁
            for (CrossFiveHeroUnion union : unionMap.values()) {
                if (union.getCampId() == 0) {
                    logger.error("五雄campId为0,activityId={},groupId={},unionUid={}", getActivityInfo().getActivityId(), groupId, union.getUnionUid());
                    continue;
                }
                for (CrossFiveHeroUnionMember unionMember : union.getMemberMap().values()) {
                    CrossFiveHeroUserData userData = getUserData(unionMember.getUserId());
                    userData.setCampId(union.getCampId());
                    userData.setUnionUid(union.getUnionUid());
                    addNeedUpdateUserData(userData);
                }
            }

            // 改状态
            crossFiveHeroData.setLockUnion(true);
            logger.error("fivehero activity {} lock union.", config.getActivityInfo().getActivityId());

            // 初始化榜单，让0值的也上榜，才能看到自己阵营都有谁
//            initAllRankList();
        }

        sendGetPatrons(syncList);
        makeUnionBook();
    }


    //弄一下商会的书
    private void makeUnionBook(){
        Map<String, Map<Integer, CrossFiveHeroBookData>> campBookMap = new ConcurrentHashMap<>();
        for(CrossFiveHeroUnion union : unionMap.values()){
            campBookMap.put(union.getUnionUid(),new ConcurrentHashMap<>());
            CrossFiveHeroBookData bookData = makeFirstBook(union);
            campBookMap.get(union.getUnionUid()).put(bookData.getNo(),bookData);
        }
        crossFiveHeroData.setBookMap(campBookMap);
    }

    private CrossFiveHeroBookData makeFirstBook(CrossFiveHeroUnion union){
        CrossFiveHeroBookData bookData = config.randomBook(new ConcurrentHashMap<>());
        bookData.setNo(1);
        bookData.setUnionUid(union.getUnionUid());
        bookData.setCampId(union.getCampId());
        bookData.setActivityId(config.getActivityId());
        bookData.setGroupId(groupId);
        addNeedInsertBookData(bookData);
        return bookData;
    }

    /**
     * 是否有资格
     */
    private boolean isAble(CrossFiveHeroUserData userData) {
        return userData.getCampId() != 0;
    }

    /**
     * 是否有资格
     */
    private boolean isAble(CrossFiveHeroUnion join) {
        return join.getCampId() != 0;
    }

    /**
     * 构建阵营
     *
     * @param unionList   参与活动的商会列表
     * @param groupParams 商会特殊分组参数
     */
    public void newMakeCamp(List<CrossFiveHeroUnion> unionList, List<Integer> groupParams) {
        synchronized (lock) {
            if (crossFiveHeroData.isLockUnion()) {
                return;
            }

            // 容错：先清空锁定数据
            for (CrossFiveHeroUserData userData : userDataMap.values()) {
                if (isAble(userData)) {
                    userData.setCampId(0);
                    userData.setUnionUid("");
                }
            }
            for (CrossFiveHeroUnion join : unionMap.values()) {
                if (isAble(join)) {
                    join.setCampId(0);
                }
            }

            // 按门客赚钱重新排序
            unionList = unionList.stream().sorted((o1, o2)
                    -> Long.compare(o2.getTotalAbility(), o1.getTotalAbility())).collect(Collectors.toList());

            for (int i = 0; i < unionList.size(); i++) {
                CrossFiveHeroUnion unionJoin = unionList.get(i);
                logger.info("按总赚钱排名{}--商会UID{}--商会总赚钱{}", i, unionJoin.getUnionUid(),
                        unionJoin.getTotalAbility());
            }

            int unionCnt = unionList.size(); // 商会总数
            int campNum = config.getCampCount(); // 阵营总数
            int idx = 0; // 遍历商会的索引
            // 将总赚钱前五名的商会分别分配至不同阵营
            PriorityBlockingQueue<Camp> camps = new PriorityBlockingQueue<>(campNum, Comparator.comparingLong(Camp::getCampAbility));
            for (; idx < Math.min(campNum, unionCnt); idx++) {
                CrossFiveHeroUnion union = unionList.get(idx);
                List<String> tmp = new ArrayList<>();
                tmp.add(union.getUnionUid());
                Camp camp = new Camp(idx + 1, tmp);
                camp.setCampAbility(union.getTotalAbility());
                camps.add(camp);
                // 修改商会信息
                union.setCampId(idx + 1);
                for (CrossFiveHeroUnionMember member : union.getMemberMap().values()) {
                    CrossFiveHeroUserData userData = getUserData(member.getUserId());
                    userData.setCampId(union.getCampId());
                    userData.setUnionUid(union.getUnionUid());
                }
            }

            // 6-20名商会分配
            int shuffleRange = groupParams.get(1); // 随机排序的范围，在保证有12个以上的商会参加则为6-20，否则取最小值
            List<CrossFiveHeroUnion> shuffled = new ArrayList<>();
            for (; idx < Math.min(shuffleRange, unionCnt); idx++) {
                shuffled.add(unionList.get(idx));
            }
            Collections.shuffle(shuffled); // 乱序

            // 用于日志记录
            for (int i = 0; i < shuffled.size(); i++) {
                CrossFiveHeroUnion unionJoin = shuffled.get(i);
                logger.info("乱序后{}--商会UID{}--商会总赚钱{}", i + campNum, unionJoin.getUnionUid(),
                        unionJoin.getTotalAbility());
            }

            // 分组，并按组总压缩战力排序
            List<List<CrossFiveHeroUnion>> groups = new ArrayList<>();
            int idx1 = 0;
            while (idx1 < shuffled.size()) {
                List<CrossFiveHeroUnion> sub = new ArrayList<>();
                while (idx1 < shuffled.size() && sub.size() < campNum) {
                    sub.add(shuffled.get(idx1++));
                }
                groups.add(sub);
            }
            groups.sort(Comparator.comparingLong(o -> o.stream().mapToLong(CrossFiveHeroUnion::getTotalAbility).sum()));

            for (int i = 0; i < groups.size(); i++) {
                List<CrossFiveHeroUnion> sub = groups.get(i);
                logger.info("乱序后{}--分组总战力{}", i,
                        sub.stream().mapToDouble(CrossFiveHeroUnion::getTotalAbility).sum());
            }

            // 优先弹出最大压缩战力
            PriorityBlockingQueue<CrossFiveHeroUnion> group =
                    new PriorityBlockingQueue<>(campNum,
                            Comparator.comparingLong(CrossFiveHeroUnion::getTotalAbility).reversed());
            for (List<CrossFiveHeroUnion> sub : groups) {
                group.addAll(sub);
                // 填充到阵营中
                Set<Camp> set = new HashSet<>(); // 存放弹出的阵营
                logger.info("分组填充");
                while (!camps.isEmpty() && !group.isEmpty()) {
                    Camp camp = camps.poll();
                    set.add(camp);
                    CrossFiveHeroUnion union = group.poll();
                    if (union == null) {
                        continue;
                    }
                    logger.info("阵营{}总赚钱{}", camp.getCampId(),
                            camp.getCampAbility());
                    logger.info("商会UID{}--商会总赚钱{}--加入阵营{}", union.getUnionUid(),union.getTotalAbility(), camp.getCampId());
                    camp.setCampAbility(camp.getCampAbility() + union.getTotalAbility());
                    camp.getUnions().add(union.getUnionUid());
                    // 修改商会信息
                    union.setCampId(camp.getCampId());
                    for (CrossFiveHeroUnionMember member : union.getMemberMap().values()) {
                        CrossFiveHeroUserData userData = getUserData(member.getUserId());
                        userData.setCampId(union.getCampId());
                        userData.setUnionUid(union.getUnionUid());
                    }
                }
                camps.addAll(set);
            }

            // 用于辅助日志
            PriorityBlockingQueue<Camp> tmpCamps =
                    new PriorityBlockingQueue<>(campNum, Comparator.comparingLong(Camp::getCampAbility));

            // 剩余商会分配
            int campUnionNum = BigDecimal.valueOf(Math.min(config.getUnionCount(), unionList.size())) // 配置数量和实际数量取最小
                    .divide(BigDecimal.valueOf(config.getCampCount()), 0, BigDecimal.ROUND_UP).intValue();
            for (; idx < unionCnt; idx++) {
                CrossFiveHeroUnion union = unionList.get(idx);
                if (!camps.isEmpty()) {
                    Camp camp = camps.poll();
                    camp.setCampAbility(camp.getCampAbility() + union.getTotalAbility());
                    camp.getUnions().add(union.getUnionUid());
                    if (camp.getUnions().size() < campUnionNum) { // 超出阵营可容纳商会数则直接将阵营弹出
                        camps.add(camp);
                    }
                    if (camp.getUnions().size() >= campUnionNum) {
                        tmpCamps.add(camp);
                    }
                    // 修改商会信息
                    union.setCampId(camp.getCampId());
                    for (CrossFiveHeroUnionMember member : union.getMemberMap().values()) {
                        CrossFiveHeroUserData userData = getUserData(member.getUserId());
                        userData.setCampId(union.getCampId());
                        userData.setUnionUid(union.getUnionUid());
                    }
                }
            }
            logger.info("阵营商会未满");
            while (!camps.isEmpty()) {
                Camp camp = camps.poll();
                logger.info("阵营{}总赚钱{}", camp.getCampId(),
                        camp.getCampAbility());
                for (int i = 0; i < camp.getUnions().size(); i++) {
                    String unionId = camp.getUnions().get(i);
                    for (CrossFiveHeroUnion union : unionList) {
                        if (union.getUnionUid().equals(unionId)) {
                            logger.info("序号{}--第{}阵营--商会UID{}--商会总赚钱{}", i, camp.getCampId(),
                                    union.getUnionUid(), union.getTotalAbility());
                        }
                    }
                }
            }

            logger.info("阵营商会已满");
            while (!tmpCamps.isEmpty()) {
                Camp camp = tmpCamps.poll();
                logger.info("阵营{}总赚钱{}", camp.getCampId(),
                        camp.getCampAbility());
                for (int i = 0; i < camp.getUnions().size(); i++) {
                    String unionId = camp.getUnions().get(i);
                    for (CrossFiveHeroUnion union : unionList) {
                        if (union.getUnionUid().equals(unionId)) {
                            logger.info("序号{}--第{}阵营--商会UID{}--商会总赚钱{}", i, camp.getCampId(),
                                    union.getUnionUid(), union.getTotalAbility());
                        }
                    }
                }
            }

            // 阵营数据生成
        }
    }

    /**
     * 原有的构建阵营逻辑
     *
     * @param unionJoinList 参与活动的商会列表
     */
    private void makeCamp(List<CrossFiveHeroUnion> unionJoinList, List<Integer> secondMatchRanges) {
        synchronized (lock) {
            if (crossFiveHeroData.isLockUnion()) {
                return;
            }

            // 容错：先清空锁定数据
            for (CrossFiveHeroUserData userData : userDataMap.values()) {
                if (isAble(userData)) {
                    userData.setCampId(0);
                    userData.setUnionUid("");
                }
            }
            for (CrossFiveHeroUnion join : unionMap.values()) {
                if (isAble(join)) {
                    join.setCampId(0);
                }
            }

            // 对第1-5名商会进行分配时，直接按照总赚钱进行阵营随机，并且三个商会必然会分在三个阵营中
            int campNum = config.getCampCount();
            int campUnionNum = BigDecimal.valueOf(Math.min(config.getUnionCount(), unionJoinList.size())) // 配置数量和实际数量取最小
                    .divide(BigDecimal.valueOf(config.getCampCount()), 0, BigDecimal.ROUND_UP).intValue();

            List<CampUnion> campUnions = unionJoinList.stream()
                    .map(superClass -> (CampUnion) superClass)
                    .collect(Collectors.toList());

            com.yanqu.road.server.manager.activity.camp.Camp.divide(campUnions, secondMatchRanges, new ArrayList<>(), campNum, campUnionNum,
                    config.getActivityInfo().getActivityId(), groupId, eCampActivityType.FIVE_HERO);

            // 阵营数据生成
        }
    }

    /**
     * 原有的构建阵营逻辑
     *
     * @param unionList 参与活动的商会列表
     */
    private void makeCamp(List<CrossFiveHeroUnion> unionList) {
        synchronized (lock) {
            if (crossFiveHeroData.isLockUnion()) {
                return;
            }

            // 容错：先清空锁定数据
            for (CrossFiveHeroUserData userData : userDataMap.values()) {
                if (isAble(userData)) {
                    userData.setCampId(0);
                    userData.setUnionUid("");
                }
            }
            for (CrossFiveHeroUnion join : unionMap.values()) {
                if (isAble(join)) {
                    join.setCampId(0);
                }
            }
            // 按门客赚钱重新排序
            unionList = unionList.stream().sorted(new Comparator<CrossFiveHeroUnion>() {
                @Override
                public int compare(CrossFiveHeroUnion o1, CrossFiveHeroUnion o2) {
                    return Long.compare(o2.getTotalAbility(), o1.getTotalAbility());
                }
            }).collect(Collectors.toList());

            Map<Integer, Long> campAbilityMap = new ConcurrentHashMap<>();
            Map<Integer, List<String>> campUnionMap = new ConcurrentHashMap<>();

            int campNum = config.getCampCount();
            int campUnionNum = BigDecimal.valueOf(Math.min(config.getUnionCount(), unionList.size())) // 配置数量和实际数量取最小
                    .divide(BigDecimal.valueOf(config.getCampCount()), 0, BigDecimal.ROUND_UP).intValue();
            for (int i = 1; i <= campNum; i++) {
                campAbilityMap.put(i, 0L);
                campUnionMap.put(i, new ArrayList<>());
            }

            // 遍历商会一个个分配
            for (CrossFiveHeroUnion join : unionList) {
                int minCamp = 1;
                long minAbility = Long.MAX_VALUE;
                for (Map.Entry<Integer, Long> entry : campAbilityMap.entrySet()) {
                    // 跳过已经分配满的阵营
                    if (campUnionMap.get(entry.getKey()).size() >= campUnionNum) {
                        continue;
                    }
                    // 取总赚钱最小的阵营（赚钱相同时，随机一下，避免一直一样）
                    if (entry.getValue() < minAbility ||
                            entry.getValue() == minAbility && randomHelper.next(2) == 0) {
                        minCamp = entry.getKey();
                        minAbility = entry.getValue();
                    }
                }

                long sum = join.getTotalAbility();
                campAbilityMap.put(minCamp, campAbilityMap.get(minCamp) + sum);
                campUnionMap.get(minCamp).add(join.getUnionUid());

                // 修改数据
                join.setCampId(minCamp);
                for (CrossFiveHeroUnionMember member : join.getMemberMap().values()) {
                    CrossFiveHeroUserData userData = getUserData(member.getUserId());
                    userData.setCampId(join.getCampId());
                    userData.setUnionUid(join.getUnionUid());
                    addNeedUpdateUserData(userData);
                }
            }

            // 阵营数据生成
        }
    }

    @Override
    public BigDecimal calcMemberCompressedAbility(long avgAbility, int unionMemberNum, List<Long> abilityParams) {
        return BigDecimal.valueOf(avgAbility);
    }

    @Override
    public CrossFiveHeroUserData getUserData(long userId) {
        initUserData(userId);
        CrossFiveHeroUserData userData = userDataMap.get(userId);
        return userData;
    }

    @Override
    public void initUserData(long userId) {
        // 生成userData
        if (!userDataMap.containsKey(userId)) {
            synchronized (lock) {
                if (!userDataMap.containsKey(userId)) {
                    CrossFiveHeroUserData userData = new CrossFiveHeroUserData();
                    userData.setActivityId(getActivityInfo().getActivityId());
                    userData.setGroupId(groupId);
                    userData.setUserId(userId);
                    UserBaseInfo baseInfo = CrossUserMgr.getUserBaseInfo(userId);
                    if(baseInfo != null){
                        userData.setServerId(baseInfo.getServerId());
                    }
                    userData.setHp(config.getEnergyMax());
                    userData.setHpTime(System.currentTimeMillis());

                    userData.setUpdateOption();

                    // 加到map
                    userDataMap.put(userId, userData);
                    addNeedInsertUserData(userData);
                }
            }
        }
    }

    @Override
    public List<CampUnion> resort(List<CampUnion> campUnions) {
        return campUnions.stream().filter(p -> p instanceof CrossFiveHeroUnion)
                .map(p -> (CrossFiveHeroUnion) p).sorted((o1, o2) ->
                        Long.compare(o2.getTotalAbility(), o1.getTotalAbility())).collect(Collectors.toList());
    }

    @Override
    public void setUnionJoinCamp(CampUnion campUnion, int campId) {
        if (campUnion == null) {
            return;
        }

        campUnion.setCampId(campId);
//        CrossFiveHeroUnion union = (CrossFiveHeroUnion) campUnion;
//        Map<Long, CrossFiveHeroUnionMember> memberMap = union.getMemberMap();
//        if (memberMap == null || memberMap.isEmpty()) {
//            logger.error("活动:{} 分组:{} 商会:{} 分阵营时，商会成员为空", getActivityInfo().getActivityId(), groupId, union.getUnionUid());
//        }
//        for (CrossFiveHeroUnionMember member : union.getMemberMap().values()) {
//            CrossFiveHeroUserData userData = getUserData(member.getUserId());
//            if (userData != null) {
//                userData.setCampId(campId);
//                userData.setUnionUid(union.getUnionUid());
//            }
//        }
    }


    public void save() {
        for(CrossFiveHeroMatch match : matchMap.values()){
            match.save();
        }
        int crossFiveHeroDataInsertCount = 0;
        int crossFiveHeroDataUpdateCount = 0;
        int unionMapInsertCount = 0;
        int unionMapUpdateCount = 0;
        if(crossFiveHeroData.isInsertOption()){
            FiveHeroBusiness.addCrossFiveHeroData(crossFiveHeroData);
        }else if(crossFiveHeroData.isUpdateOption()){
            FiveHeroBusiness.updateCrossFiveHeroData(crossFiveHeroData);
        }
        if(System.currentTimeMillis() < 1688659200000L){
            logger.info("五熊保存数据:crossFiveHeroDataInsertCount:{}",crossFiveHeroDataInsertCount);
            logger.info("五熊保存数据:crossFiveHeroDataUpdateCount:{}",crossFiveHeroDataUpdateCount);
            logger.info("五熊保存数据:needInsertUserDataList:{}",unionMapInsertCount);
            logger.info("五熊保存数据:unionMapUpdateCount:{}",unionMapUpdateCount);
            logger.info("五熊保存数据:needInsertUserDataList:{}",needInsertUserDataList.size());
            logger.info("五熊保存数据:needUpdateUserDataList:{}",needUpdateUserDataList.size());
            logger.info("五熊保存数据:needInsertPatronsDataList:{}",needInsertPatronsDataList.size());
            logger.info("五熊保存数据:needUpdatePatronsDataList:{}",needUpdatePatronsDataList.size());
            logger.info("五熊保存数据:needInsertBookDataList:{}",needInsertBookDataList.size());
            logger.info("五熊保存数据:needUpdateBooksDataList:{}",needUpdateBooksDataList.size());
        }

        for (CrossFiveHeroUnion union : unionMap.values()) {
            if (union.isInsertOption()) {
                FiveHeroBusiness.addCrossFiveHeroUnionData(union);
            } else if (union.isUpdateOption()) {
                FiveHeroBusiness.updateCrossFiveHeroUnionData(union);
            }
        }

        List<CrossFiveHeroUserData> tempUserInsertList;
        synchronized (needInsertUserDataList) {
            tempUserInsertList = new ArrayList<>(needInsertUserDataList);
            needInsertUserDataList.clear();
        }
        if (tempUserInsertList.size() > 0) {
            FiveHeroBusiness.addCrossUserDataList(tempUserInsertList);
        }


        List<CrossFiveHeroUserData> tempUserUpdateList;
        synchronized (needUpdateUserDataList) {
            tempUserUpdateList = new ArrayList<>(needUpdateUserDataList);
            needUpdateUserDataList.clear();
        }
        if (tempUserUpdateList.size() > 0) {
            FiveHeroBusiness.updateCrossUserDataList(tempUserUpdateList);
        }


        List<CrossFiveHeroPatrons> tempPatronsInsertList;
        synchronized (needInsertPatronsDataList) {
            tempPatronsInsertList = new ArrayList<>(needInsertPatronsDataList);
            needInsertPatronsDataList.clear();
        }
        if (tempPatronsInsertList.size() > 0) {
            FiveHeroBusiness.addCrossPatronsDataList(tempPatronsInsertList);
        }


        List<CrossFiveHeroPatrons> tempPatronsUpdateList;
        synchronized (needUpdatePatronsDataList) {
            tempPatronsUpdateList = new ArrayList<>(needUpdatePatronsDataList);
            needUpdatePatronsDataList.clear();
        }
        if (tempPatronsUpdateList.size() > 0) {
            FiveHeroBusiness.updateCrossPatronsDataList(tempPatronsUpdateList);
        }


        List<CrossFiveHeroBookData> tempBookInsertList;
        synchronized (needInsertBookDataList) {
            tempBookInsertList = new ArrayList<>(needInsertBookDataList);
            needInsertBookDataList.clear();
        }
        if (tempBookInsertList.size() > 0) {
            FiveHeroBusiness.addCrossBookDataList(tempBookInsertList);
        }


        List<CrossFiveHeroBookData> tempBookUpdateList;
        synchronized (needUpdateBooksDataList) {
            tempBookUpdateList = new ArrayList<>(needUpdateBooksDataList);
            needUpdateBooksDataList.clear();
        }
        if (tempBookUpdateList.size() > 0) {
            FiveHeroBusiness.updateCrossBookDataList(tempBookUpdateList);
        }

    }


    /**
     * 重新加载配置
     */
    public void reloadConfig(FiveHeroConfig tempConfig) {
        config = tempConfig;
    }

    /**
     * 热更
     */
    public void repair() {

    }

    public void loginByCmd(long userId, FiveHeroProto.CrossFiveHeroLoginReqMsg reqMsg) {
        CrossFiveHeroUserData userData = getUserData(userId);
        userData.setLanguage(reqMsg.getLanguage());
        long oldIntegral = userData.getIntegral();
        CrossFiveHeroMatch match = getMatch();
        if(oldIntegral != reqMsg.getPopularity()){
            //記錄每日加了多少
            userData.setIntegral(reqMsg.getPopularity());
            if(match != null){
                match.changeRank(userId);
                long cutValue = reqMsg.getPopularity() - oldIntegral;
                match.addToddayPop(userId,cutValue);
            }
            notifyConditionChange(userId, eGamePlayerEventType.FiveHeroPopularity, userData.getIntegral());
            userData.setIntegralTime(System.currentTimeMillis());
            addNeedUpdateUserData(userData);
        }
        syncUserDataMsg(userId);
        if(userData.getCampId() != 0 && reqMsg.getPatronsCount() != 0){
            if(ActivityHelper.activityInTime(getActivityInfo()) && userData.getPatronsMap().size() == 0){
                //不更新了，自己点同步再更新吧
                updatePatrons(userId,reqMsg.getPatronsList(), reqMsg.getCurioAddition());
            }
            checkAddItemNum(userId);
        }
        //登录的时候移除掉
        if(reqMsg.getPatronsCount() != 0){
            if(match != null){
                match.getInMap().remove(userId);
            }
        }
        syncRedDotMsg(userId);
        if(match != null){
            match.syncTokenScore(userId,false);
        }
    }

    //去本服把背包的道具设置一致
    private void checkAddItemNum(long userId){
        FiveHeroProto.CrossFiveHeroCheckItemMsg.Builder checkMsg = FiveHeroProto.CrossFiveHeroCheckItemMsg.newBuilder();
        CrossFiveHeroUserData userData = getUserData(userId);
        Map<Integer, Integer> itemMap = userData.getAddItemMap();
        for(GoodsInfo goodsInfo : GoodsMgr.getFiveHeroAddItem()){
            if(!itemMap.containsKey(goodsInfo.getGoodsId())){
                itemMap.put(goodsInfo.getGoodsId(),0);
            }
        }
        for(int goodsId : itemMap.keySet()){
            FiveHeroProto.CrossFiveHeroAddItemMsg.Builder itemMsg = FiveHeroProto.CrossFiveHeroAddItemMsg.newBuilder();
            itemMsg.setActivityId(config.getActivityId());
            itemMsg.setUserId(userId);
            itemMsg.setItem(goodsId);
            itemMsg.setNum(itemMap.get(goodsId));
            checkMsg.addGood(itemMsg);
        }
        sendPacket(GameProtocol.S_FIVEHERO_REVIVE_CHECK_ITEM_FROM_CROSS, checkMsg, userId);

    }

    public void syncRedDotMsg(long userId){
        CrossFiveHeroUserData userData = getUserData(userId);
        if(userData != null && userData.getCampId() != 0 && userData.getRedDotMap().size() > 0){
            FiveHeroProto.FiveHeroRedDotSyncMsg.Builder syncMsg = FiveHeroProto.FiveHeroRedDotSyncMsg.newBuilder();
            syncMsg.setActivityId(getActivityInfo().getActivityId());
            syncMsg.addAllType(userData.getRedDotMap().keySet());
            sendPacket(ClientProtocol.U_FIVEHERO_RED_DOT_SYNC, syncMsg, userId);
        }
    }

    private void notifyConditionChange(long userId, eGamePlayerEventType type, long value) {
        if (type != eGamePlayerEventType.FiveHeroPopularity) {
            return;
        }

        FiveHeroProto.CrossFiveHeroNotifyConditionRespMsg.Builder builder = FiveHeroProto.CrossFiveHeroNotifyConditionRespMsg.newBuilder();
        builder.setUserId(userId);
        builder.setConditionType(type.getValue());
        builder.setValue(value);
        sendPacket(GameProtocol.S_FIVEHERO_NOTIFY_CONDITION_FROM_CROSS, builder, userId);
    }

    public void syncUserDataMsg(long userId){
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.syncUserDataMsg(userId);
        }
    }

    protected void sendPacket(int code, AbstractMessage.Builder<?> messageBuilder, long userId) {
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo == null) {
            return;
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(code, messageBuilder);
        MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, message);
    }

    private CrossFiveHeroMatch getMatch(){
        return matchMap.get(1);
    }

    public void sendGetPatrons(List<Long> userIdList){
        Map<Long,List<Long>> serverUserIdMap = new ConcurrentHashMap<>();
        for(long userId : userIdList){
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if(userBaseInfo == null)continue;
            if(!serverUserIdMap.containsKey(userBaseInfo.getServerId())){
                serverUserIdMap.put(userBaseInfo.getServerId(),new ArrayList<>());
            }
            serverUserIdMap.get(userBaseInfo.getServerId()).add(userId);
        }
        for(long serverId : serverUserIdMap.keySet()){
            FiveHeroProto.CrossFiveHeroUpdatePatronsReqMsg.Builder userMsg = FiveHeroProto.CrossFiveHeroUpdatePatronsReqMsg.newBuilder();
            userMsg.setGroupId(groupId);
            userMsg.setActivityId(getActivityInfo().getActivityId());
            userMsg.addAllUserIdList(serverUserIdMap.get(serverId));
            MessageHelper.sendPacket(serverId, 0,
                    YanQuMessageUtils.buildMessage(GameProtocol.S_FIVEHERO_CROSS_GET_PATRONS, userMsg));
        }
    }

    public void syncPatrons(FiveHeroProto.CrossFiveHeroUpdatePatronsRespMsg reqMsg) {
        for(FiveHeroProto.CrossFiveHeroUpdatePatronsUserMsg uMsg : reqMsg.getUsersList()){
            CrossFiveHeroUserData userData = getUserData(uMsg.getUserId());
            if(userData.getCampId() != 0){
                updatePatrons(uMsg.getUserId(),uMsg.getPatronsList(), uMsg.getCurioAddition());
            }
        }
    }

    public void updatePatrons(long userId,FiveHeroProto.CrossFiveHeroUpdatePatronsRespMsg reqMsg) {
        FiveHeroProto.FiveHeroUpdatePatronsAbilityRespMsg.Builder respMsg = FiveHeroProto.FiveHeroUpdatePatronsAbilityRespMsg.newBuilder();
        CrossFiveHeroUserData userData = getUserData(userId);
        long nowTime = System.currentTimeMillis();
        if(nowTime - userData.getUpdatePatronsTime() < config.getSyncPatronsCd()){
            respMsg.setRet(GameErrorCode.E_FIVE_HERO_PATRONS_SYNC_CD_ERR);
            sendPacket(ClientProtocol.U_FIVEHERO_UPDATE_PATRONS, respMsg, userId);
            return;
        }
        CrossFiveHeroMatch match = getMatch();
        long oldZhanli = match.getAllAddValuePatronsUp(userData.getUserId());
        for(FiveHeroProto.CrossFiveHeroUpdatePatronsUserMsg uMsg : reqMsg.getUsersList()){
            CrossFiveHeroUserData syncUserData = getUserData(uMsg.getUserId());
            if(syncUserData.getCampId() != 0){
                updatePatrons(uMsg.getUserId(),uMsg.getPatronsList(), uMsg.getCurioAddition());
            }
        }
        respMsg.setRet(0);
        respMsg.setUpdateTime((int)(userData.getUpdatePatronsTime()/1000));
        sendPacket(ClientProtocol.U_FIVEHERO_UPDATE_PATRONS, respMsg, userId);
//        syncUserDataMsg(userId);
        long nowZhanli = match.getAllAddValuePatronsUp(userData.getUserId());

        int channelId = ConfigHelper.getInt("channelId");
        if(channelId == 666 || channelId == 702 || channelId == 703){
            logger.error("玩家{}同步战力,同步前{},同步后{},差值{}",userId,oldZhanli,nowZhanli,nowZhanli - oldZhanli);
        }
        match.syncUserDataMsg(userData.getUserId(),nowZhanli - oldZhanli);
    }

    private void updatePatrons(long userId, List<FiveHeroProto.FiveHeroPatronsTempMsg> pMsgList, long curioAddition){
        CrossFiveHeroMatch match = getMatch();
        CrossFiveHeroUserData userData = getUserData(userId);
        synchronized (userData){
            userData.setCurioAddition(curioAddition);
            Map<Integer, CrossFiveHeroPatrons> patronsMap = userData.getPatronsMap();
            for(FiveHeroProto.FiveHeroPatronsTempMsg pMsg : pMsgList){
                if(patronsMap.containsKey(pMsg.getId())){
                    CrossFiveHeroPatrons patrons = patronsMap.get(pMsg.getId());
                    if(pMsg.getAbility() > patrons.getAbility() || pMsg.getAddPer() != patrons.getAddPer()){
                        long oldValue = patrons.getAbility();
                        long newValue = pMsg.getAbility();
                        if(match != null){
                            oldValue = match.getPatronsMaxBlood(patrons);
                        }
                        patrons.setSkin(pMsg.getSkin());
                        patrons.setAbility(pMsg.getAbility());
                        patrons.setAddPer(pMsg.getAddPer());
                        if(match != null){
                            newValue = match.getPatronsMaxBlood(patrons);
                        }
                        patronsMap.put(patrons.getId(),patrons);
                        addNeedUpdatePatronsData(patrons);
//                        CrossFiveHeroLog.addLogFiveHeroPatronsUpdate(new LogFiveHeroPatronsUpdate(
//                                groupId,
//                                config.getActivityInfo().getActivityId(),
//                                userId,
//                                userData.getCampId(),
//                                patrons.getId(),
//                                2,
//                                newValue - oldValue,
//                                oldValue,
//                                newValue
//                        ));
                    }

                }else{
                    CrossFiveHeroPatrons patrons = new CrossFiveHeroPatrons(groupId,config.getActivityId(), pMsg.getId(),userId, pMsg.getSkin(), pMsg.getAbility(), pMsg.getAddPer());
                    patronsMap.put(patrons.getId(),patrons);
                    addNeedInsertPatronsData(patrons);
                }
                userData.setPatronsMap(patronsMap);
                addNeedUpdateUserData(userData);
            }
            userData.setUpdatePatronsTime(System.currentTimeMillis());
        }

    }
    //职位变了c
    public void notifyUnionMemberChangeByCmd(FiveHeroProto.CrossFiveHeroNotifyUnionMemberChangeReqMsg reqMsg) {
        // 没报名，不管
        CrossFiveHeroUnion unionInfo = unionMap.get(reqMsg.getUnionUid());
        if (unionInfo == null) {
            return;
        }
        // 结束了，不管
        if (System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000L) {
            return;
        }
        // 重新拉一下商会成员数据
        sendGetUnionMsg(Collections.singletonList(reqMsg.getUnionUid()));
    }
    //去商会跨服拉取所有人信息
    public void sendGetUnionMsg(List<String> unionUidList) {
        FiveHeroProto.CrossFiveHeroGetUnionReqMsg.Builder builder = FiveHeroProto.CrossFiveHeroGetUnionReqMsg.newBuilder();
        builder.setActivityId(config.getActivityInfo().getActivityId());
        List<Long> serverIdList = config.getActivityInfo().getServerIdList();
        builder.setGameServerId(serverIdList.get(new Random().nextInt(serverIdList.size())));
        for (String s : unionUidList) {
            builder.addUnionUid(s);
        }
        builder.setGroupId(groupId);
        MessageHelper.sendPacket(builder.getGameServerId(), 0, YanQuMessageUtils.buildMessage(CrossProtocol.C3_CROSS_FIVE_HERO_GET_UNION_REQ, builder));

    }

    public void updateUnionByCmd(FiveHeroProto.CrossFiveHeroGetUnionRespMsg reqMsg) {
        List<Long> syncList = new ArrayList<>();

        synchronized (lock) {

            // 时间
            boolean lockUnion = crossFiveHeroData.isLockUnion();
            boolean activityEnd = System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000L;

            // 结束了就无法操作了
            if (activityEnd) {
                return;
            }

            List<FiveHeroProto.FiveHeroUnionMsg> rankList = reqMsg.getUnionList().stream().sorted(new Comparator<FiveHeroProto.FiveHeroUnionMsg>() {
                @Override
                public int compare(FiveHeroProto.FiveHeroUnionMsg o1, FiveHeroProto.FiveHeroUnionMsg o2) {
                    BigInteger bigInt1 = new BigInteger(o1.getUnionInfo().getTotalEarnSpeed());
                    BigInteger bigInt2 = new BigInteger(o2.getUnionInfo().getTotalEarnSpeed());
                    return bigInt2.compareTo(bigInt1);
                }
            }).collect(Collectors.toList());

            // 遍历数据一个个处理
            for (FiveHeroProto.FiveHeroUnionMsg unionMsg : rankList) {

                // 【商会处理】
                CrossFiveHeroUnion union = unionMap.get(unionMsg.getUnionUid());
                if(union == null)continue;
                // 【成员处理】
                Map<Long, CrossFiveHeroUnionMember> oldMap = union.getMemberMap();
                if (!lockUnion) {
                    Map<Long, CrossFiveHeroUnionMember> memberMap = new ConcurrentHashMap<>();
                    for (FiveHeroProto.FiveHeroUnionMemberInfoMsg msg : unionMsg.getMemberList()) {
                        CrossFiveHeroUnionMember member = oldMap.remove(msg.getUserId());
                        if (member == null) {
                            member = new CrossFiveHeroUnionMember(msg.getUserId(), msg.getServerId());
                            syncList.add(member.getUserId()); // 添加报名状态同步
                        }
                        member.setPosition(msg.getPosition());
                        memberMap.put(member.getUserId(), member);
                    }
                    union.setMemberMap(memberMap);
                    syncList.addAll(oldMap.keySet()); // 添加报名状态同步
                } else {
                    for (FiveHeroProto.FiveHeroUnionMemberInfoMsg msg : unionMsg.getMemberList()) {
                        CrossFiveHeroUnionMember member = oldMap.get(msg.getUserId());
                        if (member != null) {
                            member.setPosition(msg.getPosition());
                        }
                    }
                }
                union.setUpdateOption();
            }
        }
        for (Long userId : syncList) {
            //同步点啥
//            syncBaseDataMsg(getUserData(userId));
        }
        updateAllUnion = true;
    }

    public void enterMap(long userId, FiveHeroProto.FiveHeroEnterReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.enterMap(userId,reqMsg);
        }else{
            FiveHeroProto.FiveHeroEnterRespMsg.Builder builder = FiveHeroProto.FiveHeroEnterRespMsg.newBuilder();
            builder.setRet(GameErrorCode.E_FIVE_HERO_SYSTEM_ERROR);
            sendPacket(ClientProtocol.U_FIVEHERO_ENTER_DATA, builder, userId);
        }
    }

    public void getCity(long userId, FiveHeroProto.FiveHeroGetCityReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.getCity(userId,reqMsg);
        }
    }

    public void enterCity(long userId, FiveHeroProto.FiveHeroEnterCityReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.enterCity(userId,reqMsg);
            // 进入场景
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if (userBaseInfo != null) {
                ScenePlayerInfo scenePlayerInfo = new ScenePlayerInfo(userBaseInfo.getServerId(), userId, userBaseInfo.getNickName(), userBaseInfo.getDecoration());
                UserScene userScene = new UserScene(
                        config.getActivityInfo().getActivityId(),
                        eSceneType.FiveHeroBattlefield.getValue(),
                        getBattlefieldSceneKey(reqMsg.getCityId()),
                        userId,
                        scenePlayerInfo,
                        System.currentTimeMillis());
                CrossSceneMgr.enterScene(userScene, false);
            }
        }
    }

    public void getPatrons(long userId, FiveHeroProto.FiveHeroGetPatronsReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.getPatrons(userId,reqMsg);
        }
    }

    public void searchCity(long userId, FiveHeroProto.FiveHeroCitySearchReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.searchCity(userId,reqMsg);
        }
    }

    public void dealEvent(long userId, FiveHeroProto.FiveHeroCityDoItReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.dealEvent(userId,reqMsg);
        }
    }

    public void revivePatrons(long userId, FiveHeroProto.FiveHeroRevivePatronsReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.revivePatrons(userId,reqMsg);
        }
    }

    public void addHp(long userId, FiveHeroProto.FiveHeroHpAddMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.addHp(userId,reqMsg.getAddValue(),3);
        }else{
            CrossFiveHeroUserData userData = getUserData(userId);
            if(userData != null){
                userData.setHp(userData.getHp() + reqMsg.getAddValue());
                addNeedUpdateUserData(userData);
                CrossAutoLogMgr.add(new LogFiveHeroUserHp(
                        groupId,
                        config.getActivityInfo().getActivityId(),
                        userId,
                        userData.getCampId(),
                        3,
                        reqMsg.getAddValue(),
                        userData.getHp()
                ));
            }
        }
    }

    public void userReport(long userId, FiveHeroProto.FiveHeroReportUserReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.userReport(userId,reqMsg);
        }
    }
    public void cityReport(long userId, FiveHeroProto.FiveHeroReportCityReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.cityReport(userId,reqMsg);
        }
    }

    public void campInfo(long userId, FiveHeroProto.FiveHeroGetCampInfoReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.campInfo(userId,reqMsg);
        }
    }

    public void getUserRankList(long userId, FiveHeroProto.FiveHeroGetUserRankReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.getUserRankList(userId,reqMsg);
        }
    }

    public CrossFiveHeroRankListModel getUserRank() {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            return  match.getUserRank();
        }
        return null;
    }

    public void campRank(long userId) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.campRank(userId);
        }
    }

    public void campUnionRank(long userId, FiveHeroProto.FiveHeroGetCampUnionRankReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.campUnionRank(userId,reqMsg);
        }
    }

    public LinkedList<CrossFiveHeroRank> campUnionRank() {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            return match.campUnionRank();
        }
        return new LinkedList<>();
    }

    public void userTokenRank(long userId) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.userTokenRank(userId);
        }
    }

    public void campTokenRank(long userId) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.campTokenRank(userId);
        }
    }

    public void selfToken(long userId) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.selfToken(userId);
        }
    }

    public void luoYangResult(long userId) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.luoYangResult(userId);
        }
    }

    public void syncChat(int range, int id, WorldMessageProto.WorldMessageTempMsg chatMsg) {
        long now = System.currentTimeMillis();
        List<Long> userIdList = new ArrayList<>();
        if (range == CrossFiveHeroChatLogic.RANGE_ALL) {
            // 所有人都要接收，所以换个发包方式
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.A_WORLD_MESSAGE_TRANSFER, chatMsg);
            ActivityChatMgr.activityChat(getActivityInfo().getActivityId(),chatMsg);
            /*for (long serverId : config.getActivityInfo().getServerIdList()) {
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }*/
            return;
        } else if (range == CrossFiveHeroChatLogic.RANGE_CAMP) {
            userIdList = userDataMap.values().stream().filter(item -> item.getCampId() == id).mapToLong(item -> item.getUserId()).boxed().collect(Collectors.toList());
        } else if (range == CrossFiveHeroChatLogic.RANGE_SYSTEM) {
            /*List<Long> list = CrossSceneMgr.getSceneUserList(config.getActivityInfo().getActivityId(),
                    eSceneType.FiveHeroBattlefield.getValue(),
                    getBattlefieldSceneKey(id),
                    23333)
                    .stream().mapToLong(item -> item.getUserId()).boxed().collect(Collectors.toList());
            userIdList.addAll(list);*/
            CrossFiveHeroMatch match = getMatch();
            if(match != null){
                userIdList = new ArrayList<>(match.getInMap());
            }
        }
        if (!userIdList.isEmpty()) {
            sendPacketToAll(ClientProtocol.U_WORLD_MESSAGE_SYNC, chatMsg.toBuilder(), userIdList);
        }
    }

    public String getBattlefieldSceneKey(int cityId) {
        return cityId + "";
    }

    protected void sendPacketToAll(int code, AbstractMessage.Builder<?> messageBuilde, Collection<Long> userIdList) {
        FiveHeroProto.FiveHeroAgentTransferMsg.Builder agentMsg = FiveHeroProto.FiveHeroAgentTransferMsg.newBuilder();
        agentMsg.setCode(code);
        for(Long userId : userIdList){
            if(userId == null){
                continue;
            }
            agentMsg.addUserId(userId);
        }
        agentMsg.setMsg(messageBuilde.build().toByteString());

        YanQuMessage message = YanQuMessageUtils.buildMessage(AgentProtocol.A_FIVE_HERO_TRANSFER, agentMsg);
        for (Long serverId : config.getActivityInfo().getServerIdList()) {
            MessageHelper.sendPacket(serverId, 0, message);
        }
    }

    public void getChatByCmd(long userId, List<Integer> paramList, int param2) {
        List<WorldMessageProto.WorldMessageTempMsg> dataList = new ArrayList<>();
        if (paramList.isEmpty()) {
            return;
        }
        CrossFiveHeroChatLogic cl = null;
        for (int range : paramList) {
            int id = 0;
            if (range == CrossFiveHeroChatLogic.RANGE_ALL) {
                id = config.getActivityInfo().getActivityId();
                cl = chatLogic;
            } else if (range == CrossFiveHeroChatLogic.RANGE_CAMP) {
                id = getUserData(userId).getCampId();
                CrossFiveHeroMatch match = getMatch();
                if(match != null){
                    cl = match.getChatLogic();
                }
            } else if (range == CrossFiveHeroChatLogic.RANGE_SYSTEM) {
                // 城池id
                id = config.getActivityId();
                CrossFiveHeroMatch match = getMatch();
                if(match != null){
                    cl = match.getChatLogic();
                }
            }

            if (range <= 0 || id <= 0) {
                continue;
            }
            dataList.addAll(cl.getChatMsg(range, id));
        }

        CrossActivityProto.CrossActivityChatListRespMsg.Builder respMsg = CrossActivityProto.CrossActivityChatListRespMsg.newBuilder();
        respMsg.setActivityId(config.getActivityInfo().getActivityId());
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo != null) {

            if (dataList.size() > 0) {
                dataList.sort(Comparator.comparingLong(WorldMessageProto.WorldMessageTempMsg::getSendTime));
                WorldMessageProto.WorldMessageListMsg.Builder worldMessageListMsg = WorldMessageProto.WorldMessageListMsg.newBuilder();
                worldMessageListMsg.addAllDataList(dataList);
                respMsg.setDataList(worldMessageListMsg);
            }
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CROSS_ACTIVITY_CHAT_LIST, respMsg);
            MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, pbMsg);
        }

    }


    public void sendChat(long userId, CrossActivityProto.CrossActivityChatReqMsg.Builder reqMsg) {
        int range = 0;
        int id = 0;
        if (eMessageType.FiveHeroPublicChat.getValue() == reqMsg.getMsg().getType()) {
            range = CrossFiveHeroChatLogic.RANGE_ALL;
            id = config.getActivityInfo().getActivityId();
            // 公屏聊天加上阵营
            WorldMessageProto.WorldMessageTempMsg.Builder message = reqMsg.getMsg().toBuilder();
            message.setExtraParams(String.valueOf(getUserData(userId).getCampId()));
            reqMsg.setMsg(message);
        } else if (eMessageType.FiveHeroCampChat.getValue() == reqMsg.getMsg().getType()) {
            CrossFiveHeroMatch match = getMatch();
            if(match != null){
                match.sendChat(userId,reqMsg);
                return;
            }
        }

        if (range <= 0 || id <= 0) {
            return;
        }

        chatLogic.chat(range, id, 1, reqMsg.getMsg(),groupId);
    }

    //跑马灯
    public void horseLamp(long userId, FiveHeroProto.FiveHeroHorseLampReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.horseLamp(userId,reqMsg);
        }
    }

    public void getRankReward(long userId, FiveHeroProto.FiveHeroGetRankRewardReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.getRankReward(userId,reqMsg);
        }
    }

    public void bookInfo(long userId) {
        FiveHeroProto.FiveHeroBookRespMsg.Builder respMsg = FiveHeroProto.FiveHeroBookRespMsg.newBuilder();
        respMsg.setRet(0);
        CrossFiveHeroUserData userData = getUserData(userId);
        if(userData != null && userData.getCampId() != 0){
            Map<Integer, CrossFiveHeroBookData> bookDataMap = crossFiveHeroData.getBookMap(userData.getUnionUid());
            CrossFiveHeroBookData nowBook = bookDataMap.get(bookDataMap.size());
            if (nowBook == null) {
                nowBook = makeFirstBook(unionMap.get(userData.getUnionUid()));
                bookDataMap.put(nowBook.getNo(),nowBook);
                crossFiveHeroData.setBookMap(userData.getUnionUid(),bookDataMap);
            }
            respMsg.setIndex(nowBook.getNo());
            respMsg.setValue(nowBook.getValue());
            for(CrossFiveHeroBookData bookData : bookDataMap.values()){
                FiveHeroProto.FiveHeroBookTempMsg.Builder bookMsg = FiveHeroProto.FiveHeroBookTempMsg.newBuilder();
                bookMsg.setIndex(bookData.getNo());
                bookMsg.setBookId(bookData.getId());
                bookMsg.setValue(bookData.getValue());
                if(bookData.isCanGetReward()){
                    bookMsg.setIsGetReward(bookData.getGetRewardUserIdList().contains(userId));
                }else{
                    bookMsg.setIsGetReward(true);
                }
                respMsg.addBook(bookMsg);
            }
        }
        sendPacket(ClientProtocol.U_FIVEHERO_BOOK_INFO, respMsg, userId);
    }

    //撰写排行榜
    public void getBookRank(long userId, FiveHeroProto.FiveHeroGetBookRankReqMsg reqMsg) {
        FiveHeroProto.FiveHeroGetBookRankRespMsg.Builder respMsg = FiveHeroProto.FiveHeroGetBookRankRespMsg.newBuilder();

        CrossFiveHeroUserData userData = getUserData(userId);
        if(userData == null || userData.getCampId() == 0){
            sendPacket(ClientProtocol.U_FIVEHERO_GET_BOOK_RANK, respMsg, userId);
            return;
        }
        Map<String, Map<Long, Integer>> campBookMakerMap = crossFiveHeroData.getBookMakerMap();
        if(campBookMakerMap.containsKey(userData.getUnionUid())){
            Map<Long, Integer> userMakerMap = new ConcurrentHashMap<>(campBookMakerMap.get(userData.getUnionUid()));
            LinkedList<CrossFiveHeroRank> rankList = new LinkedList();
            for(long makerId : userMakerMap.keySet()){
                CrossFiveHeroRank rank = new CrossFiveHeroRank(makerId + "",userMakerMap.get(makerId),0);
                rankList.add(rank);
            }
            rankList.sort(new CrossFiveHeroRankSort());
            int rankNum = 0;
            for(CrossFiveHeroRank rank : rankList){
                rankNum++;
                long makerId = Long.valueOf(rank.getId());
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(makerId);
                if(userBaseInfo == null){
                    continue;
                }
                FiveHeroProto.FiveHeroBookRankMsg.Builder bookRankMsg = FiveHeroProto.FiveHeroBookRankMsg.newBuilder();
                bookRankMsg.setRank(rankNum);
                bookRankMsg.setServerId(userBaseInfo.getServerId());
                bookRankMsg.setUserId(makerId);
                bookRankMsg.setNickName(userBaseInfo.getNickName());
                bookRankMsg.setValue((int)rank.getValue());
                respMsg.addRank(bookRankMsg);
            }
        }
        sendPacket(ClientProtocol.U_FIVEHERO_GET_BOOK_RANK, respMsg, userId);
    }

    //给数加值
    public void addBook(long userId, FiveHeroProto.CrossFiveHeroBookAddMsg reqMsg) {
        int addValue = reqMsg.getAddValue();
        CrossFiveHeroUserData userData = getUserData(userId);
        if(userData.getCampId() == 0){
            return;
        }
        Map<String, Map<Integer, CrossFiveHeroBookData>> campBookDataMap = crossFiveHeroData.getBookMap();
        Map<Integer, CrossFiveHeroBookData> bookDataMap = campBookDataMap.get(userData.getUnionUid());
        synchronized (bookDataMap){
            CrossFiveHeroBookData nowBook = bookDataMap.get(bookDataMap.size());
            FiveHeroBookConfig bookConfig = config.getBookConfig(nowBook.getId());
            if(nowBook.getValue() + addValue >= bookConfig.getSchedule()){
                addValue = nowBook.getValue() + addValue - bookConfig.getSchedule();
                nowBook.setValue(bookConfig.getSchedule());
            }else{
                nowBook.setValue(nowBook.getValue() + addValue);
            }
            CrossAutoLogMgr.add(new LogFiveHeroBook(
                    groupId,
                    config.getActivityInfo().getActivityId(),
                    userId,
                    userData.getUnionUid(),
                    bookConfig.getQuality(),
                    bookConfig.getId(),
                    nowBook.getValue(),
                    nowBook.getValue() >= bookConfig.getSchedule() ? 1 : 0,
                    nowBook.getNo()
            ));
            if(nowBook.getValue() >= bookConfig.getSchedule()){
                CrossFiveHeroBookData bookData = config.randomBook(bookDataMap);
                bookData.setNo(bookDataMap.size() + 1);
                bookData.setUnionUid(userData.getUnionUid());
                bookData.setCampId(userData.getCampId());
                bookData.setActivityId(config.getActivityId());
                bookData.setGroupId(groupId);
                bookData.setValue(addValue);
                bookDataMap.put(bookData.getNo(),bookData);
                addNeedInsertBookData(bookData);
                FiveHeroBookConfig newbookConfig = config.getBookConfig(bookData.getId());
                CrossAutoLogMgr.add(new LogFiveHeroBook(
                        groupId,
                        config.getActivityInfo().getActivityId(),
                        userId,
                        userData.getUnionUid(),
                        newbookConfig.getQuality(),
                        newbookConfig.getId(),
                        bookData.getValue(),
                        bookData.getValue() >= bookConfig.getSchedule() ? 1 : 0,
                        bookData.getNo()
                ));
            }

            campBookDataMap.put(userData.getUnionUid(),bookDataMap);
            crossFiveHeroData.setBookMap(campBookDataMap);
            Map<String, Map<Long, Integer>> bookMakerMap = crossFiveHeroData.getBookMakerMap();
            if(!bookMakerMap.containsKey(userData.getUnionUid())){
                bookMakerMap.put(userData.getUnionUid(),new ConcurrentHashMap<>());
            }
            bookMakerMap.get(userData.getUnionUid()).put(userId,bookMakerMap.get(userData.getUnionUid()).getOrDefault(userId,0) + reqMsg.getTimes());
            crossFiveHeroData.setBookMakerMap(bookMakerMap);
            addNeedUpdateBookData(nowBook);
        }

    }

    //领取书进度条满了的奖励
    public void getBookReward(long userId, FiveHeroProto.FiveHeroGetBookRewardReqMsg reqMsg) {
        FiveHeroProto.FiveHeroGetBookRewardRespMsg.Builder respMsg = FiveHeroProto.FiveHeroGetBookRewardRespMsg.newBuilder();
        respMsg.setRet(0);
        List<Integer> noList = reqMsg.getIndexList();
        CrossFiveHeroUserData userData = getUserData(userId);
        if(userData != null && userData.getCampId() != 0){
            Map<Integer, CrossFiveHeroBookData> noBookMap = crossFiveHeroData.getBookMap(userData.getUnionUid());
            for(Integer no : noList){
                if(!noBookMap.containsKey(no)){
                    respMsg.setRet(GameErrorCode.E_FIVE_HERO_PARAMS_ERR);
                    sendPacket(ClientProtocol.U_FIVEHERO_GET_BOOK_REWARD, respMsg, userId);
                    return;
                }
                CrossFiveHeroBookData bookData = noBookMap.get(no);
                if(bookData.getGetRewardUserIdList().contains(userId)){
                    respMsg.setRet(GameErrorCode.E_FIVE_HERO_BOOK_GET_REWARD);
                    sendPacket(ClientProtocol.U_FIVEHERO_GET_BOOK_REWARD, respMsg, userId);
                    return;
                }
                if(!bookData.isCanGetReward()){
                    respMsg.setRet(GameErrorCode.E_FIVE_HERO_BOOK_GET_REWARD);
                    sendPacket(ClientProtocol.U_FIVEHERO_GET_BOOK_REWARD, respMsg, userId);
                    return;
                }
            }
            FiveHeroProto.CrossFiveHeroBookRewardNoticeMsg.Builder noticeMsg = FiveHeroProto.CrossFiveHeroBookRewardNoticeMsg.newBuilder();
            noticeMsg.setActivityId(config.getActivityId());
            for(Integer no : noList){
                CrossFiveHeroBookData bookData = noBookMap.get(no);
                List<Long> list = bookData.getGetRewardUserIdList();
                list.add(userId);
                bookData.setGetRewardUserIdList(list);
                addNeedUpdateBookData(bookData);
                FiveHeroProto.FiveHeroBookTempMsg.Builder bookMsg = FiveHeroProto.FiveHeroBookTempMsg.newBuilder();
                bookMsg.setIndex(no);
                bookMsg.setBookId(bookData.getId());
                bookMsg.setValue(bookData.getValue());
                bookMsg.setIsGetReward(true);
                noticeMsg.addBook(bookMsg);
            }
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, YanQuMessageUtils.buildMessage(GameProtocol.S_FIVEHERO_GET_BOOK_REWARD_FROM_CROSS, noticeMsg));
        }
    }

    public void getWinnerInfo(long userId, FiveHeroProto.FiveHeroGetWinnerReqMsg reqMsg) {
        FiveHeroProto.FiveHeroGetWinnerRespMsg.Builder respMsg = FiveHeroProto.FiveHeroGetWinnerRespMsg.newBuilder();
        respMsg.setRet(0);
        Map<Integer, Long> winnerMap = crossFiveHeroData.getWinnerMap();
        for(Integer campId : winnerMap.keySet()){
            long winnerId = winnerMap.get(campId);
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(winnerId);
            if(userBaseInfo != null){
                FiveHeroProto.FiveHeroWinnerMsg.Builder winnerMsg = FiveHeroProto.FiveHeroWinnerMsg.newBuilder();
                winnerMsg.setUserId(winnerId);
                winnerMsg.setCampId(campId);
                winnerMsg.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                winnerMsg.setWorshipTime(0);
                respMsg.addWinner(winnerMsg);
            }
        }
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        //领奖的记录在本服，去本服弄一下
        MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, YanQuMessageUtils.buildMessage(GameProtocol.S_FIVEHERO_GET_WINNER_INFO_FROM_CROSS, respMsg));
    }

    public void readRedDot(long userId, FiveHeroProto.FiveHeroReadRedDotReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.readRedDot(userId,reqMsg);
        }
    }

    public void logGift(long userId, FiveHeroProto.CrossFiveHeroGiftLogMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.logGift(userId,reqMsg);
        }
    }

    public void getAbilityAdd(long userId, FiveHeroProto.FiveHeroAbilityAddReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.getAbilityAdd(userId,reqMsg);
        }
    }

    //
    public void abilityAddItem(long userId, FiveHeroProto.CrossFiveHeroAddItemMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.abilityAddItem(userId,reqMsg);
        }
    }

    public void lookScore(long userId, FiveHeroProto.FiveHeroCampScoreDetailReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.lookScore(userId,reqMsg);
        }
    }

    public void battlePvpRecord(long userId, FiveHeroProto.FiveHeroBattleRecordReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.battlePvpRecord(userId,reqMsg);
        }
    }

    public void tokenScore(long userId, FiveHeroProto.FiveHeroTokenScoreReqMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.tokenScore(userId,reqMsg);
        }
    }

    public Map<String, CrossFiveHeroUnion> getUnionMap() {
        return unionMap;
    }

    public Map<Integer, CrossFiveHeroRankListModel> getCampUnionRankMap() {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            return match.getCampUnionRankMap();
        }
        return  new ConcurrentHashMap<>();
    }

    public LinkedList<CrossFiveHeroRank> getCampScoreRankList() {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            return match.getCampScoreRankList(true);
        }
        return  new LinkedList<>();
    }

    public void offLineUser(FiveHeroProto.CrossFiveHeroUserOffOnlineMsg reqMsg) {
        CrossFiveHeroMatch match = getMatch();
        if(match != null){
            match.offLineUser(reqMsg.getUserIdList());
        }
    }
}
